home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BBS in a Box 7
/
BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso
/
Files
/
Prog
/
N-P
/
PopUp.cpt
/
PopUp
/
TrackPopUp.a
next >
Wrap
Text File
|
1987-05-13
|
11KB
|
354 lines
; TrackPopUp.a
; by Steve Brecher
; Copyright 1987 Software Supply
; All Publication Rights Reserved
; Permission is hereby granted to translate this source code work to
; computer-executable object or machine code and to distribute the translation
; without restriction. However, this work may not be published in printed
; form without express permission of the copyright holder.
; If this routine is incorporated in a software product, the author would
; appreciate (but does not require) credit where feasible.
; Set tabs to 10
Load 'MacDefs.d' ;all of the Apple-supplied EQUates
; This code makes extensive use of "Pascal-ish" macros. The macros are
; identical to those which are supplied in the ProgStructMacs.a file that
; comes with MPW 2.0 (forthcoming as of May 1987) with a couple of exceptions:
; I use "Subr" instead of "Procedure"; and my version of the "Call" macro
; automatically generates an Import for any routine which is undefined.
; Refer to the MPW Asm listing output file to see the macro expansions.
; The Asm listing will also supply (in the object code portion) the values
; of symbols and that might not be defined in older EQUate files.
Load 'SBMacs.d'
;
; function TrackPopUp(MHndl: MenuHandle;
; thePt: Point; {starting cursor location}
; crsrItem: integer; {item# of item to be initially under cursor}
; ): integer; {item# of selected item, 0 if none}
;
; Call this routine when the user clicks on something which should present a
; pop-up menu. Pass the global location of the click in thePt. If the menu is
; to be drawn such that the cursor is initially in the first item, pass 1 in
; crsrItem; if in the second item, pass 2, etc.
;
; Notes:
; --This code will work on all Macintosh products from 128K to Mac II, including
; Mac XL. If the large menu bar option is enabled with a Radius FPD, the
; pop up menu will use the special 16-point FPD font.
; --CalcMenuSize(MHndl) must have been called prior to calling TrackPopUp (it need be
; called only once at program startup if the items aren't changed).
; --PopUpMenuSelect is used only on a Mac II even if the trap is otherwise
; available. This is because PopUpMenuSelect is perceptibly slower than our
; own code when running on, e.g., a Mac Plus. PopUpMenuSelect is available
; on any Mac running System 4.1 or later; this routine can be shortened by
; about half if altered to assume the trap is always available.
; --The code tests for the existence of the PopUpMenuSelect trap and an
; up-to-date MDEF even when running on a Mac II, for historical reasons.
; --If there is insufficient memory to create a handle for saving the bits under
; the menu, MemErr will be set, no menu will display, and 0 will be returned.
; This doesn't apply when the _PopUpMenuSelect trap is used; the trap is smart
; enough to cause an update event for the area under the menu if it can't get
; RAM for saving the bits.
; --thePt is assumed to be on the main screen (i.e., within screenBits.bounds).
; --Menu edges are guaranteed to be at least 1 pixel from the sides of the screen
; and at least 2 pixels from the menu bar or bottom of the screen. The
; crsrItem argument will not be honored if the menu has to be moved up/down
; more than half an item in order fulfill the 2-pixel guarantee. The 2-pixel
; margin is necessary for compatibility with the PopUpMenuSelect trap.
; --The Control Panel setting for chosen item flashes is overridden by the
; following value if the Panel setting is larger. To honor the Panel setting,
; set the following value to 128.
MaxFlashes Equ 128 ;limit flashes of chosen item to this
Export Function TrackPopup(MHndl:L, thePt: L, crsrItem):W
Var theBitMap:bitMapRec, SavePort:L, saveItem
Var ColorMenu, SaveRGBBackColor:6
Begin Save=D3-D6/A2-A4
; This code will make use of an application global, MenuBarHt: integer, which
; contains the menu bar height. If the application does not supply such
; a global, comment out the following line, and conditional assembly directives
; below will adapt to its absence.
Import MenuBarHt:Data ;remove if not available in appl globals
if &Type('MenuBarHt') = 'UNDEFINED' then
MoveQ #20,D4 ;menu bar height if 64K ROM
Tst ROM85
Bmi.S @0
Move MBarHeight,D4 ;128+K ROM
@0
else
MoveQ #0,D4
Move MenuBarHt(A5),D4
endif
Move D4,TopMenuItem ;needed for new MDEF, doesn't hurt old
Call _GetPort(SavePort(FP):A)
Move.L WmgrPort,A2
Call _SetPort(A2:L)
Call FPDHndl ;Radius FPD info handle in A0 <> nil?
Beq.S CalcPos ;no
Move.L (A0),A0 ;yes...
Btst #5,1(A0) ;FPD big menu bar in use?
Beq.S CalcPos ;no
Call SetFPD(#$0100) ;yes, set largeFontEnable:=true, dontReposition=false
Move #16,txSize(A2) ;use special 16 point Chicago
MoveQ #-1,D0
Move D0,CurFMFamily ;invalidate FM cache...
Move D0,FONDID
CalcPos Call _CountMItems:W(MHndl(FP):L),D2
Move.L MHndl(FP),A0
Move.L (A0),A0
Move.L menuWidth(A0),D1 ;D1.hi=width, D1.lo=height
MoveQ #0,D0
Move D1,D0 ;height
Divu D2,D0 ;height per item
Move D0,D3
Sub crsrItem(FP),D2 ;number of items to be below cursor
Mulu D2,D0 ;height of items below cursor
Move D3,D2
Lsr #1,D2 ;D2 = half of an item's height
Add D2,D0 ;height below cursor
Sub D0,D1 ;height above cursor
MoveQ #2,D2 ;const for later
Move.L thePt(FP),D0
Swap D0
Sub.L D1,D0 ;left, top of rect
Swap D0 ;top, left of rect
AddQ #8,D0 ;shift it so cursor is 8 in from right
Cmp D2,D0 ;too far left? (min margin 1 to left of frame)
Bge.S @0 ;no
Move D2,D0 ;yes, shift it right: left=2, frame at 1
@0 Lea theBitMap+bounds(FP),A3
Sub.L OneOne,D0 ;top left of frame
Move.L D0,(A3)
Move.L menuWidth(A0),D1
Swap D1 ;height, width
Add.L #$30003+8,D1 ;height, width incl. frame & shadow
;and extra right margin for balance
Add.L D1,D0 ;bot,right of shadow
Move.L (A5),A0
Move.L screenBits+bounds+botRight(A0),D2
SubQ #2,D2
Sub D0,D2 ;margin of at least 1 to right?
Bpl.S @1 ;yes
Add D2,D0 ;no, move left...
Add D2,left(A3)
@1 Swap D2 ;screenBits.bounds.bottom
SubQ #3,D2
Swap D0 ;right, bot of frame
Sub D0,D2 ;margin of at least 2 on bottom?
Bpl.S @2 ;yes
Add D2,D0 ;no, move up...
Add D2,top(A3)
@2 Swap D0
Move.L D0,botRight(A3) ;bot, right of shadow
Move MenuBarHt(A5),D2
AddQ #2,D2
Sub top(A3),D2 ;too high?
Ble.S @3 ;no, ok
Add D2,top(A3) ;yes, move down
Add D2,bottom(A3)
@3 Cmp #$3FFF,ROM85 ;Mac II or later?
Sls ColorMenu(A6) ;tentatively, true if color Mac
Bhi.S @5 ;earlier than Mac II
Move #$9F,D0 ;unimplemented core routine
_GetTrapAddress NewTool
Move.L A0,A1
MoveQ #$0B,D0
_GetTrapAddress NewTool ;_PopUpMenuSelect installed?
Cmp.L A0,A1
Beq.S @5 ;no
Bsr MDEFHandle
Move.L (A0),A0
Cmp #10,10(A0) ;got the right MDEF for PopUpMenuSelect?
Blo.S @5 ;no
SubQ #4,SP ;yes, use _PopUpMenuSelect; result space
Push.L MHndl(FP)
Call _InsertMenu((SP):L, #-1) ;must be "hierarchical"
MoveQ #1,D2
Add top(A3),D2 ;top excl frame
Move thePt+v(FP),D0
Sub D2,D0 ;height above cursor
Ext.L D0
Divu D3,D0 ;items above one cursor is to be in
Move D0,D1
Mulu D3,D0 ;height above top of cursor's item
Add D2,D0 ;top of cursor's item
Push D0
Push left(A3)
AddQ #1,(SP) ;excl frame
AddQ #1,D1
Push D1 ;cursor's item
_PopUpMenuSelect
Pop TrackPopUp(FP)
Pop A0
Beq.S @4
Move A0,TrackPopUp(FP)
@4 Bra Done
@5 Clr TrackPopUp(FP)
Add #15,D1 ;calc shadowed rowbytes...
Lsr #4,D1
Add D1,D1
Move D1,D0 ;D0 = rowbytes
Move D0,rowBytes-bounds(A3)
Swap D1 ;D1 = height
Mulu D1,D0 ;byte size
_NewHandle ;get handle for saved bits
Bne RstFPD ;whoops
Push.L A0 ;save handle on stack for later
Move.L (A0),baseAddr-bounds(A3) ;save the pixels in the menu's area...
Call _CopyBits(portBits(A2):A, baseAddr-bounds(A3):A, A3:L, A3:L, #srcCopy, #0:L)
Tst.B ColorMenu(FP) ;color Mac?
Beq.S @7 ;no
Call _GetMCEntry:L(#0:L),D3 ;color menu?
Sne ColorMenu(FP) ;remember to restore backcolor if so
Beq.S @7 ;no
Move.L WMgrCPort,A2 ;yes, use color WMgrPort for drawing
Call _SetPort(A2:L)
Call _GetBackColor(SaveRGBBackColor(FP):A) ;save old backcolor
Move.L D3,A0 ;menu color table's menubar entry
Call _RGBBackColor(mctRGB2(A0):A)
@7 Call _ClipRect(portRect(A2):A)
Move.L OneOne,D3
Sub.L D3,botRight(A3) ;rect sans shadow
Call _EraseRect(A3:L)
Call _FrameRect(A3:L)
Push right(A3) ;draw shadow...
Push top(A3)
AddQ #3,(SP)
Push.L botRight(A3)
Push left(A3)
AddQ #3,(SP)
Push bottom(A3)
_MoveTo
_LineTo
_LineTo
Call _InsetRect(A3:L, D3:L) ;rect sans frame
Sub top(A3),D4 ;D4 = -(dist from top of popup to menu bar)
Swap D4
Call _SetOrigin(D4:L) ;fool MDEF, which draws top at v=menubar ht
Call _OffsetRect(A3:L, D4:L) ;and adjust our rect accordingly
Call _ClipRect(A3:L) ;clip to inside of frame
MoveQ #mDrawMsg,D0 ;draw the items
Bsr CallMDEF
TrackIt: Call _GetMouse(thePt(FP):A)
MoveQ #mChooseMsg,D0
Bsr CallMDEF
Call _WaitMouseUp:B(),CC
Bne.S TrackIt
MouseUp: Move TrackPopUp(FP),saveItem(FP)
Beq.S NoFlash
Move menuFlash,D4
Beq.S NoFlash
Move.L thePt(FP),D5
SubQ #1,D4 ;adjust menu flash for DBra
Cmp #MaxFlashes-1,D4 ;limit per EQU (after Dbra adjust)
Bls.S @0
MoveQ #MaxFlashes-1,D4
@0 Clr.L thePt(FP)
Bsr Flasher
Move.L D5,thePt(FP)
Bsr Flasher
Dbra D4,@0
Move saveItem(FP),TrackPopUp(FP)
NoFlash: Call _SetOrigin(#0:L) ;restore WMgr(C)Port's origin
Call _ClipRect(portRect(A2):A) ;and restore its clipRgn
Clr D4
Neg.L D4
Call _OffsetRect(A3:L, D4:L) ;restore rect to 0-origin basis
Call _InsetRect(A3:L, #-1:D0) ;restore bits, incl frame
Add.L D3,botRight(A3) ;and incl shadow
Tst.B ColorMenu(FP) ;restore back color if we changed it...
Beq.S @0
Call _RGBBackColor(SaveRGBBackColor(FP):A)
Move.L WMgrPort,A2 ;revert to old style port for CopyBits
Call _SetPort(A2:L)
@0 Call _CopyBits(baseAddr-bounds(A3):A, portBits(A2):A, A3:L, A3:L, #srcCopy, #0:L)
Pop.L A0 ;bits handle
_DisposHandle
RstFPD: Call SetFPD(#0) ;if FPD, largeFontEnable := false
Beq.S Done ;no FPD
Clr txSize(A2) ;must clear after DisposHandle if FPD
MoveQ #-1,D0
Move D0,CurFMFamily ;invalidate FM cache...
Move D0,FONDID
Done: Call _SetPort(savePort(FP):L) ;restore port
Return
Flasher MoveQ #mChooseMsg,D0
Bsr.S CallMDEF
Move #3,A0
_Delay
Rts
CallMDEF: Push D0 ;msg
Bsr.S MDefHandle ;A0 = MDEF Handle, A1 = MenuHandle
_HLock
Move.L (A0),A0
Push.L A1 ;menu handle
Push.L A3 ;rect
Push.L thePt(FP)
Pea TrackPopUp(FP)
Jsr (A0)
Bsr.S MDefHandle
_HUnlock
Rts
MDefHandle:
Move.L MHndl(FP),A1
Move.L (A1),A0
Move.L menuDefHandle(A0),A0
Rts
EndP
FPDHndl Proc Export ;sets A0 = Radius INFO handle, CCR Z flag reflects
Call _GetNamedResource:L(#'INFO':L, FPDName:A),D0
Move.L D0,A0
Rts
Export SetFPD
; Procedure SetFPD(Bytes4And5: integer)
; if FPD exists, set values of byte 4 = largeFontEnable and byte 5 = dontReposition
; Sets Z flag if no FPD (Beq NoFPD)
SetFPD: Bsr.S FPDHndl
Beq.S @0
Push.L A0
Move.L (A0),A0
Move 4+4(SP),4(A0)
Clr.L 6(A0) ;always use FPD default cursor routine
Push.L #'INFO'
Push0
Pea FPDName
_AddResource
MoveQ #-1,D0 ;clear Z flag
@0 Pop.L A0
AddQ #2,SP
Jmp (A0)
String Pascal
FPDName: DC.B 'Radius Display'
End